package ro.inf.bomberman;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

//################################### Anfang Player-Klasse ################################
/**
 * Klasse die die Playerlogik implementiert
 *
 * @author Tobias
 */
public class Player extends Explosion implements Drawable {

// --------------------------------- Player Zustände --------------------------------------	
    private String name;
    private Size size;
    private Coordinate position, destination;
    private boolean playerState;
    private GameField spielfeld;
    private int movementSpeed = 200;
    private Field savedField;
    private int dx, dy;
    private boolean boLeft = false, boRight = false, boDown = false,
            boUp = false, boA = false, boD = false, boS = false, boW = false;
    private int keyCounter = 0;
    private Game game;
    private int spielerNr;
    private static int naechsterSpieler = 1;
    private PlayerModel playermodel;
    private boolean collided;
    private int bombCounter = 0;

// --------------------------------- Player Konstruktor --------------------------------------
    /**
     * Konstruktor für die Player-Klasse
     *
     * @author Tobias
     * @param name
     * @param size
     * @param position
     * @param spielfeld
     * @param g
     */
    public Player(String name, Size size, Coordinate position,
            GameField spielfeld, Game g) {
        super(position, spielfeld, 0);
        this.name = name;
        this.size = size;
        this.position = position;
        this.playerState = true;
        this.spielfeld = spielfeld;
        this.savedField = spielfeld.mapCoordToField(position);
        this.savedField.registerObject(this);
        this.game = g;
        this.game.addKeyListener(new KeyInputHandler());
        this.spielerNr = naechsterSpieler++;
        this.playermodel = new PlayerModel(this.name);
    }

// --------------------------------- Player Bewegung --------------------------------------
    /**
     * Gibt zurück ob bewegt werden kann und führt eventuell eine Bewegung aus.
     *
     * @author Tobias
     * @param delta
     * @return boolean
     */
    public boolean move(long delta) {

        long x = (int) delta * dx / 1000;
        long y = (int) delta * dy / 1000;


// ----------------------------------Kollisionsbehandlung --------------------------------------

        Coordinate leftupDestination = new Coordinate(this.position.getX() + (int) x,
                this.position.getY() + (int) y);
        Collision leftupCollision = new Collision(leftupDestination,
                this.spielfeld, this);
        Coordinate rightupDestination = new Coordinate(this.position.getX() + (int) x + 20,
                this.position.getY() + (int) y);
        Collision rightupCollision = new Collision(rightupDestination,
                this.spielfeld, this);
        Coordinate leftbottomDestination = new Coordinate(this.position.getX() + (int) x,
                this.position.getY() + (int) y + 20);
        Collision leftbottomCollision = new Collision(leftbottomDestination,
                this.spielfeld, this);
        Coordinate rightbottomDestination = new Coordinate(this.position.getX() + (int) x + 20,
                this.position.getY() + (int) y + 20);
        Collision rightbottomCollision = new Collision(rightbottomDestination,
                this.spielfeld, this);
        this.collided = true;

        if (leftupCollision.collisionCheck() == false
                && rightupCollision.collisionCheck() == false
                && leftbottomCollision.collisionCheck() == false
                && rightbottomCollision.collisionCheck() == false) {
            this.collided = false;
        }

// ------------------------------------- Tastenzähler ---------------------------------------

        if (this.spielerNr == 1) {
            if (this.boLeft == true) {
                this.keyCounter++;
            }
            if (this.boRight == true) {
                this.keyCounter++;
            }
            if (this.boDown == true) {
                this.keyCounter++;
            }
            if (this.boUp == true) {
                this.keyCounter++;
            }
        } else if (this.spielerNr == 2) {
            if (this.boA == true) {
                this.keyCounter++;
            }
            if (this.boD == true) {
                this.keyCounter++;
            }
            if (boS == true) {
                this.keyCounter++;
            }
            if (boW == true) {
                this.keyCounter++;
            }
        }

// ---------------------------------------- Bewegung -------------------------------------------

        if (false == this.collided && this.keyCounter == 1) {
            this.destination = new Coordinate(this.position.getX(), this.position.getY());
            this.destination.setX(this.position.getX() + (int) delta * this.dx / 1000);
            this.destination.setY(this.position.getY() + (int) delta * this.dy / 1000);

            Field fieldToGo = this.spielfeld.mapCoordToField(this.destination);

            if (this.savedField.removeObject(this) == true && fieldToGo.registerObject(this) == true) {
                this.position.setX(this.position.getX() + (int) delta * this.dx / 1000);
                this.position.setY(this.position.getY() + (int) delta * this.dy / 1000);
                this.savedField = fieldToGo;
            } else if (this.savedField.removeObject(this) == true) {
                this.savedField.registerObject(this);
            } else {
            }
        }
        this.keyCounter = 0;
        return true;
    }

    // ----------------------------------- Player Bombenlegen ---------------------------------------- 
    /**
     * Gibt zurück ob eine Bombe gelegt werden kann und führt diese Aktion
     * eventuell aus.
     *
     * @author Tobias
     * @return boolean
     */
    public boolean plantBomb() {
        boolean ret = false;
        if (this.spielfeld.mapCoordToField(this.position).containsBomb() == false && this.bombCounter < 2) {
            new Bomb(new Coordinate(this.position.getX(), this.position.getY()), this.spielfeld, 3000, this.spielerNr);
            ret = true;
            this.bombCounter++;
        }
        return ret;
    }
    /**
     * Gibt die Anzahl der Bomben die von dem Spieler gelegt wurden und auf dem Feld sind zurück.
     * @author Michi
     * @return int Die Anzahl der Bomben auf dem Spielfeld dieses Spielers.
     */
    public int getBombCounter() {
        return this.bombCounter;
    }

    /**
     * Aus Steuerungs-Gründen muss diese Funktion angeboten werden. Setzt die Variable auf n.
     * @param n Die Zahl auf die die Variable geändert werden soll.
     */
    public void setNaechsterSpieler(int n) {
        this.naechsterSpieler = n;
    }

    /**
     * Setzt die Bombenanzahl für den Spieler.
     * @author Michi
     * @param counter Die Anzahl auf die gesetzt werden soll.
     */
    public void setBombCounter(int counter) {
        this.bombCounter = counter;
    }

// ----------------------------------- Player "Explodieren" --------------------------------------    
    /**
     * Überladen der vererbten explosion. Wenn Spieler "explodiert" wird sein
     * Status auf tot gesetzt.
     *
     * @author Tobias
     */
    public void explode() {
        this.updatePlayerState(false);
        this.game.stopGame(game);
    }

// ---------------------------------- Getter-/Setter-Methoden --------------------------------------   
    /**
     * Gibt zurück ob der Spieler tot oder lebendig ist.
     *
     * @author Tobias
     * @return boolean
     */
    public boolean getPlayerState() {
        return this.playerState;
    }

    /**
     * Ändert den Status des Players von lebendig -> tot, oder umgekehrt.
     *
     * @author Tobias
     * @param state
     */
    public void updatePlayerState(boolean state) {
        this.playerState = state;
    }

    /**
     * Gibt die Größe des Players in Pixel zurück.
     *
     * @author Tobias
     * @return Size
     */
    public Size getSize() {
        return this.size;
    }

    /**
     * Gibt die aktuelle Position des Players zurück.
     *
     * @author Tobias
     * @return Coordinate
     */
    public Coordinate getPosition() {
        return this.position;
    }

    /**
     * Gibt die Spielernummer zurück.
     *
     * @return int spielerNr
     */
    public int getSpielerNummer() {
        return this.spielerNr;
    }

//################################### Anfang Eingabe-Klasse ################################
    /**
     * Klasse die die Benutzereingaben regelt.
     *
     * @author Tobias
     *
     */
    public class KeyInputHandler extends KeyAdapter {

// ----------------------------------- Key Pressed ----------------------------------------
        /**
         * Überprüft ob eine Taste gedrückt wird
         *
         * @author Tobias
         * @param e
         */
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
            if (spielerNr == 1) {
                if (key == KeyEvent.VK_LEFT) {
                    dx = -movementSpeed;
                    boLeft = true;
                }
                if (key == KeyEvent.VK_RIGHT) {
                    dx = movementSpeed;
                    boRight = true;
                }
                if (key == KeyEvent.VK_UP) {
                    dy = -movementSpeed;
                    boUp = true;
                }
                if (key == KeyEvent.VK_DOWN) {
                    dy = movementSpeed;
                    boDown = true;
                }
            } else if (spielerNr == 2) {
                if (key == KeyEvent.VK_A) {
                    dx = -movementSpeed;
                    boA = true;
                }
                if (key == KeyEvent.VK_D) {
                    dx = movementSpeed;
                    boD = true;
                }
                if (key == KeyEvent.VK_W) {
                    dy = -movementSpeed;
                    boW = true;
                }
                if (key == KeyEvent.VK_S) {
                    dy = movementSpeed;
                    boS = true;
                }
            }
        }

// ----------------------------------- Key Released ----------------------------------------        
        /**
         * Überprüft ob eine Taste losgelassen wird
         *
         * @author Tobias
         * @param e
         */
        public void keyReleased(KeyEvent e) {
            int key = e.getKeyCode();
            if (spielerNr == 1) {
                if (key == KeyEvent.VK_LEFT) {
                    dx = 0;
                    boLeft = false;
                }
                if (key == KeyEvent.VK_RIGHT) {
                    dx = 0;
                    boRight = false;
                }
                if (key == KeyEvent.VK_UP) {
                    dy = 0;
                    boUp = false;
                }
                if (key == KeyEvent.VK_DOWN) {
                    dy = 0;
                    boDown = false;
                }
            } else if (spielerNr == 2) {
                if (key == KeyEvent.VK_A) {
                    dx = 0;
                    boA = false;
                }
                if (key == KeyEvent.VK_D) {
                    dx = 0;
                    boD = false;
                }
                if (key == KeyEvent.VK_W) {
                    dy = 0;
                    boW = false;
                }
                if (key == KeyEvent.VK_S) {
                    dy = 0;
                    boS = false;
                }
            }
        }

// ----------------------------------- Key Typed ----------------------------------------          
        /**
         * Überprüft ob eine Taste angeschlagen wird
         *
         * @author Tobias
         * @param e
         */
        public void keyTyped(KeyEvent e) {
            int key = e.getKeyChar();
            if (spielerNr == 1) {
                if (key == 10) {
                    plantBomb();
                }
            } else if (spielerNr == 2) {
                if (key == 32) {
                    plantBomb();
                }
            }
        }
    }
//################################# Ende Eingabe-Klasse ###################################
}
//################################# Ende Player-Klasse #####################################
